User:Unmaker/Savegame format

Saved games in Doom are stored in a binary format with the DSG extension. There is a total of six slots for saved games, each with the corresponding doomsav*.dsg file, numbered from 0 to 5.

Because Doom originally had to work in rather constrained memory conditions, it had to do writing and reading saved games in a simplistic and straightforward way. For this task, it does not make use of its Zone memory allocation, instead employing a static buffer (in fact, it even reuses a portion of the screen buffers memory) and writing/reading into it byte-by-byte. While it works much faster than the direct file input and output on an old system like DOS, it has an inherent problem of possibly overrunning the static buffer. The buffer size is set at 180,244 bytes (0x2c000) and, unlike with the demo recording, cannot be increased by the user. With large and complex levels the amount of data that must be saved can easily exceed that amount, causing a savegame buffer overflow. In this case the game exits with an error message.

The following are the details of the savegame format. Because most of its data is interpreted by the engine in a programmatical way (it loads the level and restores the game state by going through its aspects), this virtually nullifies the feasibility of the manual hacking of saved games, one exception being the player data.

Header
40 bytes in size.

General level parameters
10 bytes in size.

Players block
Each player block is 280 bytes in size, padded to 4 bytes. First block is always present; the rest are saved only if corresponding player is currently in game. When loading player data, Doom does not actually check for connected network nodes, simply placing and setting up map things according to the saved game's contents.

TODO: what actually happens after loading when there are not enough players connected?

The following is the binary contents of the player_t structure for the first player. Following player blocks, if any, are offset by 0x118 each.

Sectors block
This (and subsequent) blocks may greatly vary in size according to the map data and current playsim state, thus their offsets must be calculated. This also makes manual hacking of these virtually impossible.

Each entry is 14 bytes in size, number of entries is the length of the SECTORS lump divided by the 26 bytes.

Lines block
An entry's size is 16 bytes for one-sided lines, and 26 bytes for two-sided ones.

The number of entries is the length of the LINEDEFS lump divided by 14 bytes.

Mobj block
Every mobj_t in the thinker list is saved. Each entry is 161 bytes, padded to 4.

Specials block
TODO

Block terminator
tc_endspecials (0x07?)

Consistency Marker
To ensure consistency, the game expects the last byte of the savegame read into the buffer to be 0x1d. Otherwise it deems the file corrupt and bombs out with an error message.